<template>
  <div>
    <h1>三级分类页面</h1>
    <p>电商分类只能为三级，拖拽之后总的层数不能超过3</p>
    <p>拖拽分为两种类型:前后，内部</p>
    <p>
      思路: 拖拽肯定是两个节点(被拖拽的对象 . 目标对象)之间的交互<br />
      1.需要判断被拖拽的节点的层数（计算拖拽的层数）<br />
      2.需要根据拖拽类型和目标对象的层数判断（判断是否能被拖拽）<br />
      3.吧拖拽之后的结果同步数据库
    </p>
    <el-switch
      v-model="draggable"
      active-color="#13ce66"
      inactive-color="#ff4949"
    >
    </el-switch>开启拖拽

    <el-tree
      @node-drop="nodeDrop"
      :default-expanded-keys="defaultExpandeKeys"
      :allow-drop="allowDrop"
      node-key="catId"
      :draggable="draggable"
      :data="data"
      :props="defaultProps"
      :expand-on-click-node="false"
    >
      <span class="custom-tree-node" slot-scope="{ node, data }">
        <span>{{ node.label }}</span>
        <span>
          <el-button type="text" size="mini" @click="() => append(data)">
            Append
          </el-button>
          <el-button type="text" size="mini" @click="() => update(data)">
            Update
          </el-button>
          <el-button
            v-if="node.childNodes.length == 0"
            type="text"
            size="mini"
            @click="() => remove(node, data)"
          >
            Delete
          </el-button>
        </span>
      </span>
    </el-tree>
    <!-----------------添加修改弹窗------------------->
    <el-dialog title="三级分类保存页面" :visible.sync="dialogTableVisible">
      <el-form :model="category">
        <el-form-item label="分类名称" label-width="120px">
          <el-input v-model="category.name" autocomplete="off"></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible = false">取 消</el-button>
        <el-button
          type="primary"
          @click="
            dialogTableVisible = false;
            save();
          "
          >确 定</el-button
        >
      </div>
    </el-dialog>
  </div>
</template>

<script>
export default {
  data() {
    return {
      updateNodes: [],
      pid: 0,
      defaultExpandeKeys: [],
      level: 1,
      catLevel: 1,
      category: {},
      draggable: false,
      dialogTableVisible: false,
      data: [],
      defaultProps: {
        children: "children",
        label: "name",
      },
    };
  },

  created() {
    this.getDataList();
  },
  methods: {
    //和数据库交互 同步数据
    /**
     * draggingNode 被拖拽的对象
     * dropNode 目标对象
     * type 拖拽的类型 before after inner
     *因为拖拽的类型不同，可能会改变pid的值
     *如果拖拽的类型为before 或者 after 那么pid的值就是目标对象的pid
     *如果拖拽的类型为inner 那么pid 就是目标对象的catId
     *数据库需要改变的字段 parentCid，catLevel，sort
     *前台需要给后台传递参数
     *已知的条件: 子元素(数组)
     *如果拖拽成功，dropNode中已有的最新数据
     *需要给后台提交的参数中又要根据拖拽类型判断
     *如果拖拽类型为前后，需要获取对象就是目标对象的父元素的子元素
     *如果拖拽类型为内部，需要获取目标对象的子元素
     *我们获取到数据都是数组，前台传递到后台的数据是一个数组，后台实现批量修改
     *
     *
     *1.第一个未知条件
     *parentCid
     *2.第二个未知条件
     *catLevel每次高边都需要传到后台吗?
     *如果拖拽类型为前后，新的层级就是目标对象的层级
     *如果拖拽类型为内部，新的层级就是目标对象的层级+1
     *3.第三个未知条件
     *sort
     *拖拽类型为前后，排序就是目标对象的父元素的子元素集合的下标
     *拖拽类型为内部，排序就是目标对象的子元素的下标
     **/
    nodeDrop(draggingNode, dropNode, type) {
      // console.log("拖拽成功",draggingNode, dropNode, type);
      if (type == "before" || type == "after") {
        this.pid = dropNode.data.parentCid;
        //计算层级
        let flag = false;
        let updateChildrenNode = null;
        if (draggingNode.data.catLevel != dropNode.data.catLevel) {
          this.level = dropNode.data.catLevel;
          flag = true;
          updateChildrenNode = draggingNode;
        }
        //收集---------------------
        if (this.pid == 0) {
          this.getUpdateNodes(dropNode.parent.data, flag, updateChildrenNode);
        } else {
          this.getUpdateNodes(
            dropNode.parent.data.children,
            flag,
            updateChildrenNode
          );
        }
      } else if (type == "inner") {
        this.pid = dropNode.data.catId;
        //计算层级
        this.level = dropNode.data.catLevel + 1;
        //收集数据
        this.getUpdateNodes(dropNode.data.children, false, null);
      }
      //查看收集之后的结果

      // console.log("收集到的数据为:",this.updateNodes)

       this.$http({
        url: this.$http.adornUrl(`/product/category/updateNodes`),
        method: "post",
        data: this.$http.adornData(this.updateNodes, false),
      }).then(({data})=>{
          console.log(data)
             if (data.code == 0) {
          this.$message({
            message: "拖拽成功",
            type: "success",
          });
          this.updateNodes=[];
          this.getDataList();
        }
      })

    },
    //收集后台需要的数据  需要一个参数 标识是否需要收集子元素
    //node被拖拽的对象
    getUpdateNodes(nodes, flag, node, level = this.level, pid = this.pid) {
      // console.log("需要被收集的元素:",nodes);
      // console.log("被拖拽的对象:",node);

      for (var i = 0; i < nodes.length; i++) {
        //  var obj={catId:nodes[i].catId,name:nodes[i].name,parentCid:this.pid,catLevel:this.level,sort:i}
        this.updateNodes.push({
          catId: nodes[i].catId,
          name: nodes[i].name,
          parentCid: pid,
          catLevel: level,
          sort: i,
        });

        //   for(var i =0;i<node.childNodes;i++){
        //  this.updateNodes.push({catId:nodes[i].catId,name:nodes[i].name,parentCid:this.pid,catLevel:this.level,sort:i});
        //}
      }
      if (flag) {
        //递归
        if (node != null) {
          this.getUpdateNodes(
            node.data.children,
            false,
            this.level + 1,
            node.data.catId
          );
        }
      }
    },
    /**
     * draggingNode 被拖拽的对象
     * dropNode 目标对象
     * type 拖拽的类型 next prev inner
     *
     **/
    allowDrop(draggingNode, dropNode, type) {
      // console.log(draggingNode, dropNode, type);
      //1.计算被拖拽对象的层数
      this.getCountLevel(draggingNode);
      // console.log("被拖拽对象的层数:", this.catLevel)
      if (type == "next" || type == "prev") {
        if (this.catLevel == 1) return true;
        if (this.catLevel == 2 && dropNode.data.catLevel != 3) return true;
        if (this.catLevel == 3 && dropNode.data.catLevel == 1) return true;
      } else if (type == "inner") {
        if (this.catLevel == 1 && dropNode.data.cattevel != 3) return true;
        if (this.catLevel == 2 && dropNode.data.cattevel == 1) return true;
      }
      return false;
    },
    getCountLevel(node) {
      //node是被拖拽的对象
      this.cattevel = 1;
      if (node.childNodes.length > 0) {
        this.catLevel = 2;
        for (var i in node.childNodes) {
          if (node.childNodes[i].childNodes.length > 0) {
            this.catLevel = 3;
            return;
          }
        }
      }
    },
    //删除------------------------
    remove(node, data) {
      console.log(node, data);
      var ids = [];
      ids.push(node.data.catId);
      this.$http({
        url: this.$http.adornUrl(`/product/category/delete`),
        method: "post",
        data: this.$http.adornData(ids, false),
      }).then(({ data }) => {
        console.log(data);
        this.getDataList();
      });
    },
    update(node) {
      this.dialogTableVisible = true;
      //后台查询 回显-----------------
      this.$http({
        url: this.$http.adornUrl(`/product/category/info/${node.catId}`), //拼接网关
        method: "get",
        params: this.$http.adornParams(),
      }).then(({ data }) => {
        console.log(data);
        this.category = data.category;
      });
    },
    //添加-------------------------
    save() {
      let methodUrl = "save";

      if (this.category.catId) methodUrl = "update";

      this.$http({
        url: this.$http.adornUrl(`/product/category/${methodUrl}`),
        method: "post",
        data: this.$http.adornData(this.category, false),
      }).then(({ data }) => {
        console.log(data);

        if (data.code == 0) {
          this.$message({
            message: "保存成功",
            type: "success",
          });
          this.defaultExpandeKeys =[this.category.parentCid];
          this.category = {};
          this.getDataList();
        }
      });
    },
    append(node) {
      console.log(node);
      this.category.parentCid = node.catId;
      this.category.catLevel = node.catLevel + 1;
      this.category.showStatus = 1;
      this.category.sort = 0;
      this.dialogTableVisible = true;
    },
    getDataList() {
      //axios
      this.$http({
        url: this.$http.adornUrl("/product/category/tree/list"), //拼接网关
        method: "get",
        params: this.$http.adornParams(),
      }).then(({ data }) => {
        console.log(data);
        this.data = data.page;
      });
    },
  },
};
</script>
